import {Component, OnInit, ViewChild} from '@angular/core';
import {WsService} from '../../services/ws.service';
declare let RTCPeerConnection: any;
@Component({
  selector: 'app-ngo2ochat',
  templateUrl: './ngo2ochat.component.html',
  styleUrls: ['./ngo2ochat.component.css']
})
export class Ngo2ochatComponent implements OnInit {
  username:string |undefined;
  toname:string | undefined;

  pc:any;
  transceiver:any;
  webcamstream:any;
  REGISTETE: string |undefined
  CALLSTATE='CALL';

  mediaConstraints={
    "audio":true,
    "video":true
  }

  @ViewChild("me") me: any;
  @ViewChild("remote") remote:any;

  constructor(private ws:WsService) { }

  ngOnInit(): void {
    this.ws.connectServer()
      .subscribe((event:any)=>{
        //console.dir(event);
        const jsonMessage = JSON.parse(event);
        switch (jsonMessage.id) {

          case "registerResponse":
            this.registerResponse(jsonMessage);
            break;

          case 'callResponse':
            this.callResponse(jsonMessage);
            break;
          case 'incomingCall':
            this.incomingCall(jsonMessage);
            break;
          case 'iceCandidate':
            this.handleIceCanDateMSG(jsonMessage);
            break;

          case 'startCommunication':
            this.startCommunication(jsonMessage);
            break;

          case 'stopCommunication':
            console.info('Communication ended by remote peer');
            this.stop();
            break;


          default:
            console.error('Unrecognized message', jsonMessage);

        }
      },(err)=>{
        console.dir(err);
      },()=>{
        console.log("连接完成")
      });
    this.creatPeerConnection();
  }




  register(){

    console.log(this.username);
    if(this.username!=undefined&&this.username!=''){
      let body={
        id:'register',
        name:this.username
      }
      this.sendMessage(body);


    }


  }

  async call(){


    if(this.pc==null){
      await  this.creatPeerConnection()

    }

    navigator.mediaDevices.getUserMedia(this.mediaConstraints)
      .then((stream:any)=>{
        this.me.nativeElement.srcObject=stream;
        this.webcamstream=stream;

        try {
          this.webcamstream.getTracks().forEach(this.transceiver = (track: any) => {
            this.pc.addTransceiver(track, {streams: [this.webcamstream]});
          })
        } catch (e) {
          console.error(e);
          console.error("获取本地媒体流错误");
        }

      })


  }

  hangup(){
   this.stop();
  }





  //// PeerConnection

  creatPeerConnection(){
    this.pc=new RTCPeerConnection();


    //console.dir(this.pc);
    this.pc.onconnectionstatechange= (event:any)=>this.handleConnectionStateChange(event);
    this.pc.onicecandidateerror=(event:any)=>this.handleIceCandidateError(event);
    this.pc.onicecandidate=(event:any)=>this.handleICECandidateEvent(event);
    this.pc.oniceconnectionstatechange=(event:any)=>this.handleICEConnectionStateChangeEvent(event);
    this.pc.onicegatheringstatechange=(event:any)=>this.handleICEGatheringStateChangeEven(event);
    this.pc.onsignalingstatechange=(event:any)=>this.handleSignalingStateChangeEvent(event);
    this.pc.onnegotiationneeded=(event:any)=>this.handleNegotiationNeededEvent(event);
    this.pc.ontrack=(event:any)=>this.handleTrackEven(event);

  }


  handleConnectionStateChange(event:any){

    console.warn("Connection State Changed to"+this.pc.connectionState);
    switch (this.pc.connectionState){
      case 'connected':
        //试试吧这里注释了，可以不指定turn 地址不
        const config=this.pc.getConfiguration();
       // console.log("Current Configuration")
       // console.dir(config);
        break;
      case 'disconnected':

        break

      case 'failed':
        console.warn("Connection Failed now restart ICE");
        this.pc.restartIce();
        setTimeout(()=>{
          if(this.pc.iceConnectionState!== 'connected'){
            console.error("restartIce failed! close video call!" + "Connection state:" + this.pc.connectionState)
           // this.closeVideoCall();
            //this.stop();
          }
        },1000*10)

        break;
    }

  }


  handleIceCandidateError(event:any){
    console.error("ICE Candidate Error, errorCode"+event.errorCode+"errorText"+event.errorText);

  }

  handleICECandidateEvent(event:any){

    console.log("handle Ice Candidate")
    //console.dir(event);
    console.log("ICE Candidate已然生成,准备发送Candicate信息到信令系统")
    if(event.candidate){
      console.log("*** Outgoing ICE candidate: "+event.candidate.candidate);
      console.log("ICE Candidate已然生成,准备发送Candicate信息到信令系统")
      // //服务端交互第2步  发送候选者信息到服务器
      let candidatestr=JSON.stringify(event.candidate);
      let body={
        id: "onIceCandidate",
        candidate: candidatestr
      }
      this.ws.sendMessage(body);

    }

  }



  handleICEConnectionStateChangeEvent(event:any){
    console.warn("*** ICE connection state changed to "+this.pc.iceConnectionState);
  }

  handleICEGatheringStateChangeEven(event:any){
    console.warn("*** ICE gathering state changed to: " + this.pc.iceGatheringState);
  }


  handleSignalingStateChangeEvent(event:any){
    console.warn("*** WebRTC signaling state changed to: " + this.pc.signalingState);
    switch (event.signalingState){
      case 'closed':
        //this.closeVideoCall();
        this.stop();
        break;
    }

  }


  async handleNegotiationNeededEvent(event:any){
    console.log("*** Negotiation needed");

    try {
      if (this.pc.signalingState != 'stable') {
        console.warn('-- The connection isn\'t stable yet; postponing...');
        return;
      }
      console.log('---> Setting local description to the offer');

      await this.pc.setLocalDescription();
      this.pc.setLocalDescription()
        .then((description:any)=>{
          console.log('---> Sending the offer to the remote peer');

          // 实锤啦 这个是第一步
          if(this.pc.localDescription.sdp){
            if(this.CALLSTATE=='CALL'){
              let body={
                id :"call",
                from:this.username,
                to:this.toname,
                sdpOffer:this.pc.localDescription.sdp
              }
              this.sendMessage(body);
              console.log("呼叫模式发送SDP");
            }
            else if(this.CALLSTATE=='ANSWER'){
              let body={
                id : 'incomingCallResponse',
                from : this.toname,
                callResponse : 'accept',
                sdpOffer : this.pc.localDescription.sdp
              }
              this.sendMessage(body);
             console.log("应答模式发送SDP");

            }
          }
        });
    } catch (e) {
      console.log("*** The following error occurred while handling the negotiationneeded event:");
    }

  }


 async handleTrackEven(event:any){
    console.warn("*** Track event  捕获到轨道");
    console.dir(event);
    console.log(event.streams);
    try {
      let remoteStream =new  MediaStream();
      remoteStream.addTrack(event.receiver.track);
      this.remote.nativeElement.srcObject=remoteStream;

    } catch (e) {
      console.error("播放视频异常");
      console.error(e);
    }
  }



  sendMessage(message:any){
    this.ws.sendMessage(message);
  }
  offSocket(){
    this.ws.close();
  }


  registerResponse(message:any){
    if(message.response=='accepted'){
      this.REGISTETE='REGISTER';
    }
    else{
      this.REGISTETE="REGISTER-FAIL";
      alert(message.message);
    }
  }


  callResponse(message:any){
    console.dir(message);
    if(message.response!='accepted'){
      console.info('Call not accepted by peer. Closing call');
      alert('对方拒绝');
    }
    else{
      var n = new RTCSessionDescription({
        type: "answer",
        sdp: message.sdpAnswer
      });
        this.pc.setRemoteDescription(n)
        .then(()=>{

        }).catch((e:any)=>{
          console.error(e);
      })

    }
  }


  //估计是应答处理

  incomingCall(message:any){

    //let aorj= window.confirm("用户"+message.from+"呼叫");
    //if(aorj==true){
      this.toname=message.from;
      navigator.mediaDevices.getUserMedia(this.mediaConstraints)
        .then((stream:any)=>{
          this.me.nativeElement.srcObject=stream;
          this.webcamstream=stream;

          try {
            this.webcamstream.getTracks().forEach(this.transceiver = (track: any) => {
              this.pc.addTransceiver(track, {streams: [this.webcamstream]});
            })
          this.CALLSTATE='ANSWER';



          } catch (e) {
            console.error(e);
            console.error("获取本地媒体流错误");
          }

        })

    //}
    // else{
    //   //拒绝接听
    //
    //   let response={
    //     id : 'incomingCallResponse',
    //     from : message.from,
    //     callResponse : 'reject',
    //     message : 'user declined'
    //   }
    //   this.sendMessage(response);
    // }


  }

  handleIceCanDateMSG(msg:any){

    //this.pc.addIceCandidate(message.candidate);
    try {
     // console.log("接收到服务端的iceCandidate"+msg.candidate);
      //console.dir(msg.candidate);
      //let candidate=JSON.parse(msg.candidate)   ;
      if(this.pc.remoteDescription){
        //console.log("准备使用的ICEcandidate");
        //console.dir(candidate);
        this.pc.addIceCandidate(new  RTCIceCandidate(msg.candidate));
        //this.pc.addIceCandidate(msg.candidate);
      }
    } catch (e) {
      console.warn('添加Candidate 发生异常');
      console.error(e);
    }

  }

  startCommunication(message:any){

    var n = new RTCSessionDescription({
      type: "answer",
      sdp: message.sdpAnswer
    });
    this.pc.setRemoteDescription(n)
      .then(()=>{

      }).catch((e:any)=>{
      console.error(e);
    })
  }


  async stop(){
    if(this.pc){
      if(this.pc.signalingState=='cloused'){
        return;
      }
      else{
       await this.webcamstream.getTracks().forEach((track:any)=>{
          track.stop();
        })
        this.webcamstream=null;
        this.pc.close();
      }


    }

    let body={
      id:"stop"
    }
    this.sendMessage(body);
  }

}
